package com.example.tetris.logics.components;

import java.io.Serializable;
import java.util.Random;

public class Brick implements Serializable {
    /**
     * 存放Brick的坐标与详细信息
     */
    private CellList cells;
    private int offsetX,offsetY;
    private SHAPE shape;

    private Board board;
    private int rotateType = 0;

    private boolean isFixed = false;
    public boolean isFixed() {
        return isFixed;
    }
    private Brick(CellList cells, int offsetX, int offsetY, SHAPE shape, Board board) {
        this.cells = cells;
        this.offsetX = offsetX;
        this.offsetY = offsetY;
        this.shape = shape;
        this.board = board;
    }

    public static Brick generateRandomBrick(Board board) {
        Random random = new Random();
        SHAPE randomShapeGenerated;
        CellList cells = new CellList();
        int randNum = random.nextInt(0,6);
        switch (randNum){
            case 0: randomShapeGenerated = SHAPE.S;break;
            case 1:randomShapeGenerated = SHAPE.J;break;
            case 2:randomShapeGenerated = SHAPE.I;break;
            case 3:randomShapeGenerated = SHAPE.O;break;
            case 4:randomShapeGenerated = SHAPE.L;break;
            case 5:randomShapeGenerated = SHAPE.T;break;
            case 6:randomShapeGenerated = SHAPE.Z;break;
            default:randomShapeGenerated = SHAPE.O;break;
        }
        SHAPE shape = randomShapeGenerated;
        int offsetX = 5;
        int offsetY = 0;
        int[][] shapeMatrix = Tetromino.getShape(shape, 0);

        for (int i = 0; i < 4; i++) {
            int y = i + offsetY;
            for (int j = 0; j < 4; j++) {
                int x = j + offsetX;
                if (shapeMatrix[i][j] != 0) {
                    cells.addCell(x, y);
                }

            }
        }
        return new Brick(cells,offsetX,offsetY,shape,board);

    }

    public boolean canFall() {
        boolean canGenerateNewBrick = true;
        for(Cell cell : cells.getCells()){
            int x = cell.getX();
            int y = cell.getY();
            if(board.isOutOfBoundary(x,y) || board.isCellOccupied(x,y)){
                canGenerateNewBrick = false;
                break;
            }
        }
        return canGenerateNewBrick;
    }

    public boolean moveDown(){
        return moveto(new int[]{0, 1});
    }
    public boolean moveLeft(){
        return moveto(new int[]{-1, 0});
    }
    public boolean moveRight(){
        return moveto(new int[]{1, 0});
    }

    private boolean moveto(int[] direction){
        int dx = direction[0],dy = direction[1];
        boolean canMove = true;
        for(Cell cell : cells.getCells()){
            int nextX = cell.getX() + dx;
            int nextY = cell.getY() + dy;
            if(board.isOutOfBoundary(nextX,nextY) || board.isCellOccupied(nextX,nextY)){
                canMove = false;
                break;
            }
        }
        if(canMove){
            for(Cell cell : cells.getCells()){
                int nextX = cell.getX() + dx;
                int nextY = cell.getY() + dy;
                cell.setX(nextX);
                cell.setY(nextY);
            }
            offsetX += dx;
            offsetY += dy;

        }
        return  canMove;
    }

    public void setFixedOnBoard(){
        isFixed = true;
        for(Cell cell : cells.getCells()){
            int x = cell.getX();
            int y = cell.getY();
            board.occupyCell(x,y);
        }
    }

    public SHAPE getShape() {
        return shape;
    }

    public CellList getBrickCellsOccupied(){
        return cells;
    }

    /**
     * 默认逆时针旋转
     * @return
     */
    public boolean rotate(){
        rotateType = (rotateType + 1) % 4;
        int[][] shapeMatrix = Tetromino.getShape(shape, rotateType);
        CellList cellsAfterRotate = new CellList();
        for (int i = 0; i < 4; i++) {
            int y = i + offsetY;
            for (int j = 0; j < 4; j++) {
                int x = j + offsetX;
                if (shapeMatrix[i][j] != 0) {
                    cellsAfterRotate.addCell(x, y);
                }
            }
        }
        boolean canRotate = true;
        for(Cell cell : cellsAfterRotate.getCells()){
            int x = cell.getX();
            int y = cell.getY();
            if(board.isOutOfBoundary(x,y) || board.isCellOccupied(x,y)){
                canRotate = false;
                break;
            }
        }
        if(canRotate){
            cells = cellsAfterRotate;
        }
        return  canRotate;
    }


}
